package main

import (
	"bytes"
	"encoding/json"
	"fmt"

	"github.com/hyperledger/fabric/core/chaincode/shim"
	pb "github.com/hyperledger/fabric/protos/peer"
)

const (
	key_prefix = ""
)

type SimpleChaincode struct {
}

func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
	return shim.Success(nil)
}

func (t *SimpleChaincode) CreateEntity(stub shim.ChaincodeStubInterface, args []string) pb.Response {

	if len(args) == 0 {
		return shim.Error("Incorrect number of arguments.")
	}

	data, err := json.Marshal(args) //转换成JSON返回的是byte[]
	if err != nil {
		return shim.Error(err.Error())
	}

	err = stub.PutState(key_prefix+args[0], data)
	if err != nil {
		return shim.Error(err.Error())
	}
	return shim.Success(nil)
}

//getEntity
func (t *SimpleChaincode) GetEntity(stub shim.ChaincodeStubInterface, args []string) pb.Response {

	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}

	value, err := stub.GetState(key_prefix + args[0])
	if err != nil {
		return shim.Error(err.Error())
	}
	if len(value) == 0 {
		return shim.Error("Key Not Found")
	}
	return shim.Success(value)
}

//getEntityByRange
func (t *SimpleChaincode) GetEntityByRange(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 2 {
		return shim.Error("Incorrect number of arguments. Expecting  2")
	}

	resultsIterator, err := stub.GetStateByRange(key_prefix+args[0], key_prefix+args[1])
	if err != nil {
		return shim.Error(err.Error())
	}
	defer resultsIterator.Close()

	var buffer bytes.Buffer
	buffer.WriteString("[")

	bArrayMemberAlreadyWritten := false
	for resultsIterator.HasNext() {
		queryResponse, err := resultsIterator.Next()
		if err != nil {

			return shim.Error(err.Error())
		}

		// 在数组成员前加一个逗号
		if bArrayMemberAlreadyWritten == true {
			buffer.WriteString(",")
		}

		buffer.WriteString(string(queryResponse.Value))
		bArrayMemberAlreadyWritten = true
	}
	buffer.WriteString("]")

	return shim.Success(buffer.Bytes())
}

func (t *SimpleChaincode) GetEntityByPrefix(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting  1")
	}

	endKey := []byte(args[0])
	endKey[len(endKey)-1] = endKey[len(endKey)-1] + 1
	args = append(args, string(endKey))
	return t.GetEntityByRange(stub, args)
}

func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
	function, args := stub.GetFunctionAndParameters()
	switch function {
	case "CreateEntity":
		return t.CreateEntity(stub, args)
	case "GetEntity":
		return t.GetEntity(stub, args)
	case "GetEntityByRange":
		return t.GetEntityByRange(stub, args)

	case "GetEntityByPrefix":
		return t.GetEntityByPrefix(stub, args)
	}

	return shim.Error("Invalid invoke function name " + function)
}

func main() {
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}
